use ahash::AHashMap;
use serde::{Deserialize, Deserializer};
use std::{hash::Hash, path::PathBuf};

// macro_rules! info {
//     (target: $target:expr, $($arg:tt)*) => {

//     };
// }

// macro_rules! warn {
//     () => {};
// }

// #[macro_export]
// macro_rules! my_info {
//     ($($arg:tt)*) => {
//         let tid = std::thread::current().id();
//         let stid = write!("{:?}", std::thread::current().id())
//         .trim_start_matches("ThreadId(")
//         .trim_end_matches(")");

//         println!("{:?}, [#{}]", tid, stid);
//         // let tid = format!("{:?}", thread::current().id()).trim_start_matches("ThreadId(").trim_end_matches(")");
//         // (target: $target:expr, $($arg:tt)*) => log::error!(format!("{#{}}", ), $($arg)+);
//     };
// }

pub fn eta_format(secs: u64) -> String {
    let remaining_seconds = secs % 60;
    let minutes = (secs % 3600) / 60;
    let hours = secs / 3600;
    let s = format!("{:02.0}:{:02.0}:{:02.0}", hours, minutes, remaining_seconds);
    s
}

// pub fn thread_id<'a>() -> &'a str {
//     format!("{:?}", thread::current().id())
//         .trim_start_matches("ThreadId(")
//         .trim_end_matches(")")
// }

// pub trait Database {}

// pub trait Table {}

// pub trait TableColumn {}

// pub trait Key {}

// pub struct SchemaRule {
//     //
//     pub schema_name: String,
//     // 排除表
//     pub exclude_tabs: Vec<String>,
//     // 包含表，比exclude_tabs优先级高
//     pub include_tabs: Vec<String>,
// }

// pub struct TableRule {
//     //
//     pub schema_name: String,
//     pub table_name: String,

//     // 排除列
//     pub exclude_cols: Vec<String>,
//     // 包含列，比exclude_cols优先级高
//     pub include_cols: Vec<String>,
// }

// #[derive(Debug, Clone, Default)]
// pub struct ComparisonRuleMap {
//     pub r1: ComparisonRule,
//     pub r2: ComparisonRule,
// }

// impl ComparisonRuleMap {
//     pub fn from(rule_string: &str) -> Self {
//         let (s1, s2) = match rule_string.split_once(":") {
//             Some((a, b)) => (a, b),
//             None => panic!("Format Error: Lack of mapping, {rule_string}"),
//         };

//         ComparisonRuleMap {
//             r1: decode_rule_detail(s1),
//             r2: decode_rule_detail(s2),
//         }
//     }
// }

// #[derive(Debug, Clone, Default, Deserialize)]
// pub struct ComparisonRule {
//     pub schema_name: String,
//     // 查询的表，优先级比exclude_tables高
//     pub tables: Option<Vec<String>>,
//     // 排除表
//     pub exclude_tables: Option<Vec<String>>,

//     // 排除列
//     pub excludes: Option<Vec<String>>,
//     // 包含列，比excludes优先级高
//     pub includes: Option<Vec<String>>,

//     // 查询条件
//     pub condition: Option<Vec<String>>,
// }

// #[inline]
// fn decode_schema_table(s: &str) -> (&str, Option<String>) {
//     match s.split_once(".") {
//         Some((schema, table)) => (schema, Some(table.to_owned())),
//         None => (s, None),
//     }
// }

// #[inline]
// fn decode_rule_detail(s: &str) -> ComparisonRule {
//     // 条件
//     match s.split_once("=>") {
//         Some((schema_table, condition)) => {
//             // table, condition
//             let (schema, table) = decode_schema_table(schema_table);
//             let mut rule = ComparisonRule::new(schema.to_owned(), table);
//             // println!("condition={condition}");
//             let condition_raw = condition.trim_start_matches("[").trim_end_matches("]");

//             let mut excludes = Vec::new();
//             let mut includes = Vec::new();
//             let mut conditions = Vec::new();

//             // 列、条件 where ID>100 AND AGE> 18
//             for cond in condition_raw.split_terminator(",") {
//                 let cond = cond.trim();
//                 if cond.starts_with("!") {
//                     // exclude
//                     // println!("exclude={}", cond.trim_start_matches("!"))
//                     excludes.push(cond.trim_start_matches("!").to_owned());
//                 } else if cond.starts_with("?") {
//                     // where
//                     // println!("where={}", cond.trim_start_matches("?"))
//                     conditions.push(cond.trim_start_matches("?").to_owned());
//                 } else {
//                     // include
//                     // println!("include={}", cond)
//                     includes.push(cond.to_owned());
//                 }
//             }

//             if excludes.len() > 0 {
//                 rule.excludes = Some(excludes);
//             }

//             if includes.len() > 0 {
//                 rule.includes = Some(includes);
//             }

//             if conditions.len() > 0 {
//                 rule.condition = Some(conditions);
//             }

//             rule
//         }
//         None => {
//             let (schema, table) = decode_schema_table(s);
//             ComparisonRule::new(schema.to_owned(), table)
//         }
//     }
// }

// impl<'de> Deserialize<'de> for ComparisonRuleMap {
//     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
//     where
//         D: Deserializer<'de>,
//     {
//         let rule_string = String::deserialize(deserializer)?;

//         let (s1, s2) = match rule_string.split_once(":") {
//             Some((a, b)) => (a, b),
//             None => panic!("Lack of mapping, {rule_string}"),
//         };

//         Ok(ComparisonRuleMap {
//             r1: decode_rule_detail(s1),
//             r2: decode_rule_detail(s2),
//         })
//     }
// }

// impl ComparisonRule {
//     pub fn new(schema_name: String, table_name: Option<String>) -> Self {
//         let tables = if let Some(table_name) = table_name {
//             Some(vec![table_name])
//         } else {
//             None
//         };
//         ComparisonRule {
//             schema_name,
//             tables,
//             exclude_tables: None,
//             excludes: None,
//             includes: None,
//             condition: None,
//         }
//     }
// }

#[derive(Debug, Clone, Default)]
pub struct RuleMap {
    pub src: Rule,
    pub tgt: Rule,
}

#[derive(Debug, Clone, Default)]
pub struct Rule {
    pub schema: Vec<RuleValue>,
    pub table: Vec<RuleValue>,
    pub column: Vec<RuleValue>,
    pub condition: Option<String>,
}

#[derive(Debug, Clone)]
pub struct RuleValue {
    pub re: bool,
    pub value: String,
    pub not: bool,
    pub pk: bool,
}

impl RuleValue {
    pub fn new(value: String, re: bool, not: bool, pk: bool) -> Self {
        // pk时，强行转换为非正则
        let re = if pk { false } else { re };
        RuleValue { value, re, not, pk }
    }
}

#[derive(Eq, Hash, PartialEq, Debug, Clone)]
pub enum KeyType {
    SCHEMA,
    TABLE,
    COLUMN,
    CONDITION,
}

// 解析规则
#[inline]
pub fn parse_rule(hay: &str) -> RuleMap {
    let mut values = Vec::new();
    // let mut map = HashMap::new();
    let mut rule = Rule::default();
    let mut array_open = false;
    let mut regex_open = false;
    let mut cond_open = false;
    let mut strings = String::new();
    let mut key: KeyType = KeyType::SCHEMA;
    let mut rule_map = RuleMap::default();
    let mut has_src_rule = false;

    for ch in hay.trim().chars() {
        match ch {
            '/' => {
                if regex_open {
                    if strings.len() > 0 {
                        let value = strings.clone().trim().to_owned();
                        let (value, not, pk) = if value.starts_with("!") {
                            (value.trim_start_matches("!"), true, false)
                        } else {
                            if value.starts_with("@") && key == KeyType::COLUMN {
                                (value.trim_start_matches("@"), false, true)
                            } else {
                                (value.as_str(), false, false)
                            }
                        };
                        values.push(RuleValue::new(value.to_owned(), regex_open, not, pk));
                        strings.clear();
                    }
                }
                regex_open = !regex_open;
            }
            '[' => {
                if regex_open {
                    strings.push(ch);
                    continue;
                }
                array_open = true;
            }

            ',' | '.' | ']' | '(' => {
                if regex_open {
                    strings.push(ch);
                    continue;
                }

                if strings.len() > 0 {
                    let value = strings.clone().trim().to_owned();
                    let (value, not) = if value.starts_with("!") {
                        (value.trim_start_matches("!"), true)
                    } else {
                        (value.as_str(), false)
                    };
                    values.push(RuleValue::new(value.to_owned(), regex_open, not, false));
                    strings.clear();
                }

                match ch {
                    '.' => {
                        if values.len() > 0 {
                            // Schema 单个正则
                            // map.insert(key.clone(), values.clone());
                            match key.clone() {
                                KeyType::SCHEMA => rule.schema = values.clone(),
                                KeyType::TABLE => rule.table = values.clone(),
                                KeyType::COLUMN => rule.column = values.clone(),
                                _ => {}
                            }
                            values.clear();
                        }
                        if key == KeyType::SCHEMA {
                            key = KeyType::TABLE;
                        }
                    }
                    ']' => {
                        if array_open {
                            match key.clone() {
                                KeyType::SCHEMA => rule.schema = values.clone(),
                                KeyType::TABLE => rule.table = values.clone(),
                                KeyType::COLUMN => rule.column = values.clone(),
                                _ => {}
                            }
                            values.clear();
                            array_open = false;
                        }
                    }
                    '(' => {
                        if values.len() > 0 {
                            match key.clone() {
                                KeyType::SCHEMA => rule.schema = values.clone(),
                                KeyType::TABLE => rule.table = values.clone(),
                                KeyType::COLUMN => rule.column = values.clone(),
                                _ => {}
                            }
                            values.clear();
                        }
                        if key == KeyType::COLUMN {
                            key = KeyType::CONDITION;
                            cond_open = true;
                        }
                    }
                    _ => {}
                }
            }

            '>' => {
                if strings == "=" {
                    if values.len() > 0 {
                        // Table 单个正则
                        match key.clone() {
                            KeyType::SCHEMA => rule.schema = values.clone(),
                            KeyType::TABLE => rule.table = values.clone(),
                            KeyType::COLUMN => rule.column = values.clone(),
                            _ => {}
                        }
                        values.clear();
                    }
                    strings.clear();
                    key = KeyType::COLUMN;
                } else if strings.ends_with("=") {
                    // Table 为全匹配
                    let value = strings.trim_end_matches("=").to_owned();
                    let (value, not) = if value.starts_with("!") {
                        (value.trim_start_matches("!"), true)
                    } else {
                        (value.as_str(), false)
                    };
                    values.push(RuleValue::new(value.to_owned(), regex_open, not, false));
                    match key.clone() {
                        KeyType::SCHEMA => rule.schema = values.clone(),
                        KeyType::TABLE => rule.table = values.clone(),
                        KeyType::COLUMN => rule.column = values.clone(),
                        _ => {}
                    }
                    values.clear();
                    strings.clear();
                    key = KeyType::COLUMN;
                } else {
                    strings.push(ch);
                }
            }
            ')' => {
                if regex_open {
                    strings.push(ch);
                    continue;
                }

                if cond_open {
                    // values.push(RuleValue::new(
                    //     strings.clone().trim().to_owned(),
                    //     false,
                    //     false,
                    // ));
                    rule.condition = Some(strings.clone().trim().to_owned());
                    strings.clear();
                    cond_open = false;
                }
            }
            ':' => {
                if regex_open {
                    strings.push(ch);
                    continue;
                }
                // 新的一个映射开始
                rule_map.src = rule.clone();
                rule = Rule::default();
                has_src_rule = true;

                key = KeyType::SCHEMA;
            }
            _ => {
                strings.push(ch);
            }
        }
    }

    match key {
        KeyType::SCHEMA | KeyType::TABLE | KeyType::COLUMN => {
            if strings.len() > 0 {
                let value = strings.clone().trim().to_owned();
                let (value, not) = if value.starts_with("!") {
                    (value.trim_start_matches("!"), true)
                } else {
                    (value.as_str(), false)
                };
                values.push(RuleValue::new(value.to_owned(), regex_open, not, false));
                strings.clear();
            }

            if values.len() > 0 {
                match key.clone() {
                    KeyType::SCHEMA => rule.schema = values.clone(),
                    KeyType::TABLE => rule.table = values.clone(),
                    KeyType::COLUMN => rule.column = values.clone(),
                    _ => {}
                }
                values.clear();
            }
        }
        KeyType::CONDITION => {
            if values.len() > 0 {
                // Table 单个正则
                match key.clone() {
                    KeyType::SCHEMA => rule.schema = values.clone(),
                    KeyType::TABLE => rule.table = values.clone(),
                    KeyType::COLUMN => rule.column = values.clone(),
                    _ => {}
                }
                values.clear();
            }
        }
    }

    rule_map.tgt = rule.clone();
    // 简写
    if !has_src_rule {
        rule_map.src = rule.clone();
    }

    rule_map
}

impl RuleMap {
    pub fn from(hay: &str) -> Self {
        parse_rule(hay)
    }
}

impl<'de> Deserialize<'de> for RuleMap {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let rule_string = String::deserialize(deserializer)?;
        Ok(parse_rule(&rule_string))
    }
}

#[derive(Debug, Clone, Default, Deserialize)]
pub struct GlobalConfig {
    // 是否计算大字段
    pub with_long_type: bool,
    // 每次查询的行数
    pub page_size: usize,
    // 计算目录，临时目录
    pub tmpdir: PathBuf,
    // 比对任务类型
    pub action: Action,
    // 分割CRC文件数
    pub buckets: u32,

    // 校验规格数组
    pub rule: Option<Vec<RuleMap>>,
    pub rule_file: Option<PathBuf>,

    pub db1: DatabaseConfig,
    pub db2: DatabaseConfig,
}

#[derive(Debug, Clone, Default)]
pub enum Action {
    // 统计行数
    #[default]
    Count,
    // 表结构
    Columns,
    // 主键
    Primarykey,
    // 非空唯一索引
    NonNullableUniqueIndex,
    // 主键或非空唯一索引
    Keys,
    // 计算全表的CRC
    CrcAll,
    // 计算指定行的CRC
    CrcRow,
    // 未知
    Unknown {
        value: String,
    },
}

impl<'de> Deserialize<'de> for Action {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        // 自定义反序列化逻辑（如处理特殊字段或格式）
        // 示例：根据字段存在性判断变体
        let value = String::deserialize(deserializer)?;
        // #   COLS: (表结构)
        // #   UI: (非空唯一索引)
        // #   PK: (主键)
        // #   KEY: (主键+非空唯一索引)
        // #   COUNT: (行数)
        // #   CRC_ALL: (表数据)
        // #   CRC_ROW: (行数据，过滤指定行）
        if value.eq_ignore_ascii_case("COLS") {
            Ok(Action::Columns)
        } else if value.eq_ignore_ascii_case("UI") {
            Ok(Action::NonNullableUniqueIndex)
        } else if value.eq_ignore_ascii_case("PK") {
            Ok(Action::Primarykey)
        } else if value.eq_ignore_ascii_case("KEY") {
            Ok(Action::Keys)
        } else if value.eq_ignore_ascii_case("COUNT") {
            Ok(Action::Count)
        } else if value.eq_ignore_ascii_case("CRC_ALL") {
            Ok(Action::CrcAll)
        } else if value.eq_ignore_ascii_case("CRC_ROW") {
            Ok(Action::CrcRow)
        } else {
            Ok(Action::Unknown { value })
        }
    }
}

#[derive(Debug, Clone, Default, Deserialize)]
pub struct DatabaseConfig {
    pub dbtype: DatabaseType,
    pub username: String,
    pub password: String,
    pub host: String,
    pub port: usize,
    // Alias: Service_name
    pub database: String,
}

#[derive(Debug, Clone, Default)]
pub enum DatabaseType {
    #[default]
    Oracle,
    MySQL,
    Postgres,
    Unknown {
        value: String,
    },
}

impl<'de> Deserialize<'de> for DatabaseType {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        // 自定义反序列化逻辑（如处理特殊字段或格式）
        // 示例：根据字段存在性判断变体
        let value = String::deserialize(deserializer)?;
        if value.eq_ignore_ascii_case("Oracle") {
            Ok(DatabaseType::Oracle)
        } else if value.eq_ignore_ascii_case("MySQL") {
            Ok(DatabaseType::MySQL)
        } else if value.eq_ignore_ascii_case("Postgres")
            || value.eq_ignore_ascii_case("Postgresql")
            || value.eq_ignore_ascii_case("PG")
        {
            Ok(DatabaseType::Postgres)
        } else {
            Ok(DatabaseType::Unknown { value })
        }
    }
}

#[derive(Debug, Clone)]
pub struct CompareConfig {
    schema: Vec<SchemaInfo>,
}

impl CompareConfig {
    pub fn new() -> Self {
        CompareConfig { schema: Vec::new() }
    }

    pub fn add_schema(&mut self, schema_name: String) {
        self.schema.push(SchemaInfo::new(schema_name));
    }

    pub fn get_schema_vec(&self) -> Vec<String> {
        self.schema.iter().map(|s| s.schema_name.clone()).collect()
    }

    pub fn schemas(&self) -> Vec<SchemaInfo> {
        self.schema.clone()
    }
}

pub struct Checksum {
    pub key: String,
    pub checksum: u32,
}

#[derive(Debug, Clone)]
pub struct SchemaInfo {
    schema_name: String,
    tables: Vec<TableInfo>,
}

impl SchemaInfo {
    pub fn new(schema_name: String) -> Self {
        SchemaInfo {
            schema_name,
            tables: Vec::new(),
        }
    }
    pub fn schema(&self) -> String {
        self.schema_name.clone()
    }

    pub fn tables(&self) -> Vec<String> {
        self.tables.iter().map(|t| t.table_name.clone()).collect()
    }
}

#[derive(Debug, Clone, Default)]
pub struct TableInfo {
    pub schema_name: String,
    pub table_name: String,
    pub cols: Vec<ColumnInfo>,
    pub nullable_cols: Vec<String>,
    pub keys: Vec<String>,
    pub crc_file_names: AHashMap<String, usize>,
    pub count: usize,
    // 查询列和查询条件
    // pub query_where: String,
    // pub query_inc_cols: Vec<String>,
    // pub query_exc_cols: Vec<String>,
}

impl TableInfo {
    pub fn new(schema_name: String, table_name: String) -> Self {
        TableInfo {
            schema_name,
            table_name,
            cols: Vec::new(),
            keys: Vec::new(),
            nullable_cols: Vec::new(),
            crc_file_names: AHashMap::new(),
            count: 0,
            // query_where: String::new(),
            // query_inc_cols: Vec::new(),
            // query_exc_cols: Vec::new(),
        }
    }

    pub fn query_nolong_col_names(&self) -> Vec<String> {
        self.cols
            .iter()
            .filter(|c| !c.long)
            .map(|c| c.query_column_name.to_owned())
            .collect::<Vec<String>>()
    }

    pub fn query_col_names(&self) -> Vec<String> {
        self.cols
            .iter()
            .map(|c| c.query_column_name.to_owned())
            .collect::<Vec<String>>()
    }
}

#[derive(Debug, Clone, Default)]
pub struct ColumnInfo {
    pub column_name: String,
    pub query_column_name: String,
    pub data_type: String,
    pub data_length: usize,
    pub nullable: bool,
    // 是否为大字段
    pub long: bool,
}

// #[derive(Debug, Clone, Default)]
// pub struct KeyInfo {
//     pub primary_key: bool,
//     pub unique_key: bool,
//     pub key_name: String,
// }

// pub trait DatabaseDialect {
//     // 传入offset和limit,返回分页SQL
//     fn paging<T, C>(
//         tab_name: T,
//         columns: Vec<C>,
//         order_by_keys: T,
//         offset: usize,
//         limit: usize,
//     ) -> T
//     where
//         T: Into<String>,
//         C: TableColumn;

//     // 查询表的列
//     fn query_tab_columns<T, C>(schema: T, table: T) -> Vec<C>
//     where
//         T: Into<String>,
//         C: TableColumn;
// }

// pub fn compare_lines_parallel(path1: &Path, path2: &Path) -> Result<bool, std::io::Error> {
//     // Zip+并行化逐行比较
//     let lines_equal = BufReader::new(File::open(path1)?)
//         .lines()
//         .zip(BufReader::new(File::open(path2)?).lines())
//         .par_bridge() // 转换为并行迭代器
//         .all(|(line1, line2)| {
//             match (line1, line2) {
//                 (Ok(l1), Ok(l2)) => {
//                     log::debug!("1111: l1: {:?}, l2: {:?}", l1, l2);
//                     l1 == l2
//                 }
//                 _ => false, // 处理IO错误或格式不一致
//             }
//         });

//     let lines_equal = BufReader::new(File::open(path2)?)
//         .lines()
//         .zip(BufReader::new(File::open(path1)?).lines())
//         .par_bridge() // 转换为并行迭代器
//         .all(|(line1, line2)| {
//             match (line1, line2) {
//                 (Ok(l1), Ok(l2)) => {
//                     log::debug!("2222: l1: {:?}, l2: {:?}", l1, l2);
//                     l1 == l2
//                 }
//                 _ => false, // 处理IO错误或格式不一致
//             }
//         });

//     // 检查文件长度是否一致
//     // let len_match = reader1.bytes().count() == reader2.bytes().count();
//     Ok(lines_equal)
// }

#[cfg(test)]
mod test {
    use crate::RuleMap;

    #[test]
    fn build_sql() {
        let s = "LBK1,LBK,!123,/*ABC*/,!/*12345*/.!/TTT*/,!EXT_EMPLOYEES=>[@/actor_id,first_name,last_name/, C1, C2, C3]";
        let rule_map = RuleMap::from(s);
        let key = "username";
        let mut in_values = vec![];
        let mut not_in_values = vec![];
        let mut params = Vec::new();
        for v in rule_map.src.schema.clone() {
            if v.re {
                continue;
            }
            params.push(v.value.clone());
            if !v.not {
                in_values.push(v.value);
            } else {
                not_in_values.push(v.value);
            }
        }

        let cond_in_values = if in_values.len() > 0 {
            format!(
                " and {key} in ({})",
                in_values
                    .iter()
                    .enumerate()
                    .map(|(i, _)| format!(":{}", i + 1))
                    .collect::<Vec<_>>()
                    .join(",")
            )
        } else {
            String::new()
        };

        let cond_not_in_values = if not_in_values.len() > 0 {
            format!(
                " and {key} not in ({})",
                not_in_values
                    .iter()
                    .enumerate()
                    .map(|(i, _)| format!(":{}", i + in_values.len() + 1))
                    .collect::<Vec<_>>()
                    .join(",")
            )
        } else {
            String::new()
        };

        // 模糊匹配
        let mut regex_likes = String::new();
        let mut not_regex_likes = String::new();
        let mut start_index = in_values.len() + not_in_values.len() + 1;
        for v in rule_map.src.schema.clone() {
            if !v.re {
                continue;
            }
            if !v.not {
                params.push(v.value.clone());
                regex_likes.push_str(&format!(" and REGEXP_LIKE ({key}, :{})", start_index));
                start_index += 1;
            }
        }

        for v in rule_map.src.schema.clone() {
            if !v.re {
                continue;
            }
            if v.not {
                params.push(v.value.clone());
                not_regex_likes
                    .push_str(&format!(" and NOT REGEXP_LIKE ({key}, :{})", start_index));
                start_index += 1;
            }
        }

        let sql_condition = format!(
            "where 1=1 {cond_in_values} {cond_not_in_values} {regex_likes} {not_regex_likes}"
        );
        println!("cond_in_values: {cond_in_values}");
        println!("cond_not_in_values: {cond_not_in_values}");
        println!("regex_likes: {regex_likes}");
        println!("not_regex_likes: {not_regex_likes}");
        println!("sql_condition: {sql_condition}");
        println!("params: {:?}", params);
        println!("columns: {:?}", rule_map.src.column);
    }

    #[test]
    fn build_sql2() {
        let s = "LBK1,LBK,!123,/*ABC*/,!/*12345*/.!/TTT*/,!EXT_EMPLOYEES";
        let rule_map = RuleMap::from(s);
        let key = "table_name";
        let s = "LBK";
        let mut in_values = vec![];
        let mut not_in_values = vec![];
        let mut params = Vec::new();
        params.push(s.to_owned());

        for v in rule_map.src.table.clone() {
            if v.re {
                continue;
            }
            params.push(v.value.clone());
            if !v.not {
                in_values.push(v.value);
            } else {
                not_in_values.push(v.value);
            }
        }

        let cond_in_values = if in_values.len() > 0 {
            format!(
                " and {key} in ({})",
                in_values
                    .iter()
                    .enumerate()
                    .map(|(i, _)| format!(":{}", i + 2))
                    .collect::<Vec<_>>()
                    .join(",")
            )
        } else {
            String::new()
        };

        let cond_not_in_values = if not_in_values.len() > 0 {
            format!(
                " and {key} not in ({})",
                not_in_values
                    .iter()
                    .enumerate()
                    .map(|(i, _)| format!(":{}", i + in_values.len() + 2))
                    .collect::<Vec<_>>()
                    .join(",")
            )
        } else {
            String::new()
        };

        // 模糊匹配
        let mut regex_likes = String::new();
        let mut not_regex_likes = String::new();
        let mut start_index = in_values.len() + not_in_values.len() + 2;
        for v in rule_map.src.table.clone() {
            if !v.re {
                continue;
            }
            if !v.not {
                params.push(v.value.clone());
                regex_likes.push_str(&format!(" and REGEXP_LIKE ({key}, :{})", start_index));
                start_index += 1;
            }
        }

        for v in rule_map.src.table.clone() {
            if !v.re {
                continue;
            }
            if v.not {
                params.push(v.value.clone());
                not_regex_likes
                    .push_str(&format!(" and NOT REGEXP_LIKE ({key}, :{})", start_index));
                start_index += 1;
            }
        }
        let sql_condition = format!(
            "where owner = :1 {cond_in_values} {cond_not_in_values} {regex_likes} {not_regex_likes}"
        );

        let sql_params: Vec<&dyn oracle::sql_type::ToSql> = params
            .iter()
            .map(|k| k as &dyn oracle::sql_type::ToSql)
            .collect();

        println!("cond_in_values: {cond_in_values}");
        println!("cond_not_in_values: {cond_not_in_values}");
        println!("regex_likes: {regex_likes}");
        println!("not_regex_likes: {not_regex_likes}");
        println!("sql_condition: {sql_condition}");
        println!("{:?}", params);

        // (sql_condition, sql_params, params)
    }
}
